type Fn = (...param: any[]) => any
/** 事件总线 - 发布订阅模式 */
export class EventBus {
    /**事件列表。键是事件名，值是依赖函数Set */
    #event = new Map<string, Set<Fn>>()
    /**订阅事件
     * @param eventName 事件名
     * @param handler 事件发布后的回调函数
     */
    subscribe(eventName: string, handler: Fn) {

        if (this.#event.has(eventName)) {
            this.#event.get(eventName)!.add(handler)
        } else {
            this.#event.set(eventName, new Set([handler]))
        }
    }
    /**发布事件
     * @param eventName 发布的事件名
     * @param argu 要传递给订阅者的参数
     */
    publish(eventName: string, ...argu: any[]) {
        this.#event.get(eventName)?.forEach((callback) => {
            try {
                callback(...argu)
            } catch (error) {
                console.log('调用函数出错：', error);
            }
        })
    }
    /**取消订阅事件
     * @param eventName 事件名
     * @param handler 想取消的函数 （传入订阅时的函数引用）
     */
    unSubscribe(eventName: string, handler: Fn) {
        this.#event.get(eventName)?.delete(handler)
    }
}
/**导出一个默认的实例。全局事件总线 */
export default new EventBus()


/* 测试代码：

    EventBus.subscribe('test', (a, b) => {
        console.log('test的第一个订阅者', a, b);
    })
    const fn2 = (a, b) => {
        console.log('test的第二个订阅者', a, b);
    }
    EventBus.subscribe('test', fn2)
    EventBus.subscribe('test', (a, b) => {
        console.log('test的第三个订阅者', a, b);
    })
    EventBus.subscribe('my', (a, b) => {
        console.log('my的第一个订阅者', a, b);
    })

    EventBus.unSubscribe('test', fn2)

    setTimeout(() => {
        EventBus.publish('test', 666, 777)
        setTimeout(() => {
            EventBus.publish('my', 888, 999)
        }, 1000);
    }, 1000);
*/